import PropTypes from 'ant-design-vue/es/_util/vue-types'
import 'ant-design-vue/es/menu/style'
import Menu from 'ant-design-vue/es/menu'
import 'ant-design-vue/es/icon/style'
import Icon from 'ant-design-vue/es/icon'
import Badge from 'ant-design-vue/es/badge'

import './style.less'

import storage from '@zh/common-utils/utils/storage'

const MenuItem = Menu.Item,
  SubMenu = Menu.SubMenu,
  httpReg = /(http|https|ftp):\/\/([\w.]+\/?)\S*/

export default {
  name: 'ZMenu',
  props: {
    menus: PropTypes.array,
    theme: PropTypes.string.def('dark'),
    mode: PropTypes.string.def('inline'),
    collapsed: PropTypes.bool.def(false),
    handleMenuSelect: {
      type: Function,
      default: () => { }
    }
  },
  data () {
    return {
      menuMap: {},
      openKeys: [],
      selectedKeys: [],
      cachedOpenKeys: [],
      cachedSelectedKeys: []
    }
  },
  computed: {
    rootSubmenuKeys (vm) {
      var keys = []
      vm.menus.forEach(function (item) {
        return keys.push(item.path)
      })
      return keys
    }
  },
  created () {
    if (Object.keys(this.menuMap).length == 0 && this.menus.length > 0) {
      menus2Map(this.menus, this.menuMap)
    }
    this.$watch('$route', function () {
      this.updateSelectedMenu()
    })
    this.$watch('collapsed', function (val) {
      if (val) {
        this.cachedOpenKeys = this.openKeys.concat()
        this.openKeys = []
      } else {
        this.openKeys = this.cachedOpenKeys
      }
    })
  },
  mounted () {
    this.updateSelectedMenu()
    if (this.openKeys.length == 0) {
      this.$router.getRoutes().map(i => {
        i.meta.expanded && this.openKeys.push(i.path)
      })
    }
  },
  methods: {
    updateSelectedMenu () {
      var routes = (this.$route.meta.matched || this.$route.matched).concat(),
        hidden = this.$route.meta.hidden

      if (routes.length >= 3 && hidden) {
        routes.pop()
        this.selectedKeys = [routes[routes.length - 1].path]
      } else {
        this.selectedKeys = [routes.pop().path]
      }

      var openKeys = []

      if (this.mode === 'inline') {
        routes.forEach(function (item) {
          item.path && openKeys.push(item.path)
        })
      }
      this.collapsed ? this.cachedOpenKeys = openKeys : this.openKeys = openKeys
    }
  },
  render (h) {
    const me = this
    return h(Menu, {
      props: {
        mode: me.mode,
        theme: me.theme,
        openKeys: me.openKeys,
        selectedKeys: me.selectedKeys
      },
      on: {
        select (menuItem) {
          me.$emit('select', menuItem)
          const target = me.menuMap[menuItem.key].meta.target
          if (target != '_blank') {
            me.selectedKeys = menuItem.selectedKeys
          }
          if (target == '_blank') {
            const token = storage.getToken().value
            window.open(me.menuMap[menuItem.key].path + '?token=' + token)
          }
          me.handleMenuSelect(me.menuMap[menuItem.key], me.menuMap)
        },
        openChange (openKeys) {
          // 在水平模式下时，不再执行后续
          if (me.mode === 'horizontal') {
            me.openKeys = openKeys
            return
          }
          const latestOpenKey = openKeys.find(function (key) {
            return !me.openKeys.includes(key)
          })
          if (!me.rootSubmenuKeys.includes(latestOpenKey)) {
            me.openKeys = openKeys
          } else {
            me.openKeys = latestOpenKey ? [latestOpenKey] : []
          }
        }
      }
    }, [me.menus.map(item => {
      if (!item.hidden) {
        return renderMenu(h, item)
      }
    })])
  }
}

function menus2Map (menus, map = {}) {
  menus.map(i => {
    map[i.path] = i
    if (i.children) {
      menus2Map(i.children, map)
    }
  })
  return map
}

function renderMenu (h, item) {
  if (item && !item.hidden) {
    return item.children && !item.hideChildrenInMenu ? renderSubMenu(h, item) : renderMenuItem(h, item)
  }
  return null
}

function renderSubMenu (h, item) {
  return h(Menu.SubMenu, {
    key: item.path,
    attrs: {
      title: h('span', [
        renderIcon(h, item.meta.icon),
        renderTitle(h, item.meta.title),
        renderBadge(h, item.meta.badge)
      ])
    }
  }, [!item.hideChildrenInMenu && item.children.map(function (childItem) {
    return renderMenu(h, childItem)
  })])
}

function renderMenuItem (h, item) {
  const meta = Object.assign({}, item.meta),
    target = meta.target || null,
    props = {
      to: { name: item.name }
    },
    attrs = {}
  if (!item.meta.target) {
    attrs.href = item.path
    attrs.target = target
  }
  return h(Menu.Item, {
    key: item.path
  }, [h('router-link', {
    props,
    attrs
  }, [
    renderIcon(h, item.meta.icon),
    renderTitle(h, item.meta.title),
    renderBadge(h, item.meta.badge)
  ])])
}

function renderMenuItemContent (h, item) {

}

function renderIcon (h, icon) {
  if (icon === undefined || icon === 'none' || icon === null || icon === '') {
    return null
  }

  var props = {}
  typeof icon === 'object' ? props.component = icon : props.type = icon
  return h(Icon, {
    props: props
  })
}

function renderTitle (h, title) {
  return h('span', [title])
}

function renderBadge (h, badge) {
  if (badge) {
    return h(Badge, {
      attrs: {
        count: badge.count,
        dot: !!badge.dot
      }
    })
  }
  return null
}
